package com.java.code.thread;

import org.junit.Test;

import java.util.concurrent.*;

public class JavaFuture {

    @Test
    public void futureTask() throws ExecutionException, InterruptedException {
        //实例化一个任务
        FutureTask task = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("---------------执行业务代码");
                return "返回";
            }
        });
        //将任务放到线程里面 让线程去执行
        Thread thread = new Thread(task);
        thread.start();
        //task.get()主线程等待任务执行完成
        //阻塞返回值是FutureTask的一个弊端,会一直while(true)等待任务完成会导致CPU资源飙升
        System.out.println(task.get());
    }

    @Test
    public void completableFuture() throws ExecutionException, InterruptedException {
        System.out.println("当前主线程name:" + Thread.currentThread().getName());
        CompletableFuture.runAsync(() -> {
            System.out.println("CompletableFuture线程name:" + Thread.currentThread().getName());
        });

        // 没有返回值
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("CompletableFuture线程name:" + Thread.currentThread().getName());
        });
        System.out.println(completableFuture.get());
        // 有返回值
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("StringCompletableFuture线程name:" + Thread.currentThread().getName());
            return "返回";
        });
        System.out.println(stringCompletableFuture.get());

        // 自定义线程池
        stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("StringCompletableFuture自定义线程池线程name:" + Thread.currentThread().getName());
            return "返回";
        }, Executors.newCachedThreadPool());
        System.out.println(stringCompletableFuture.get());
    }


    @Test
    public void excute() throws ExecutionException, InterruptedException {
        // A线程执行完后 吧执行结果交给B线程 B线程拿到A线程的执行结果之后再执行B线程
        CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("A线程name:" + Thread.currentThread().getName());
            return "返回1";
        }).thenAcceptAsync(res -> {
            System.out.println("B线程name:" + Thread.currentThread().getName());
            System.out.println(res);
        }, Executors.newCachedThreadPool());

        //线程A抛异常
        CompletableFuture.runAsync(() -> {
            System.out.println("C线程name:" + Thread.currentThread().getName());
            int i = 1 / 0;
        }).exceptionally(e -> {
            System.out.println("D线程name:" + Thread.currentThread().getName());
            System.out.println(e.getMessage());
            return null;
        });

        CompletableFuture.supplyAsync(() -> {
            System.out.println("E线程name:" + Thread.currentThread().getName());
            return "E";
        }).whenCompleteAsync((a, b) -> {//等E线程结束后在执行
            System.out.println("F线程name:" + Thread.currentThread().getName());
            System.out.println(a);
        });
    }

    @Test
    public void parallelExcute() {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "1");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "2");
        // future1 和 future2都执行完之后再执行一段逻辑
        future1.thenCombine(future2, (a, b) -> a + "   " + b)
                .thenAcceptAsync(s -> System.out.println(s)); //直接消费掉
    }
}
